module mxu_pmb_rdgen (
    input logic             clk,
    input logic             rst_n,
          mxu_cfg_if.pmb_in mxu_cfg,
          pmb_rd_req_if.out mxu_pmb_rd_req
);

    logic cfg_rdy, cfg_vld;
    logic        last_req_in_instr;
    logic [23:0] pmb_base_addr;

    assign cfg_vld       = ~cfg_rdy;
    assign pmb_base_addr = mxu_cfg.pmb_addr;

    always_ff @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            cfg_rdy <= 1'b1;
        end else if (cfg_rdy == 1'b0) begin
            if (lst_req_in_instr && mxu_pmb_rd_req.vld && mxu_pmb_rd_req.rdy) begin
                cfg_rdy <= 1'b1;
            end
        end else begin
            if (mxu_cfg.vld && mxu_cfg.rdy) begin
                cfg_rdy <= 1'b0;
            end
        end
    end

    logic [15:0] slice_n1;
    logic [15:0] slice_m1;
    logic [15:0] m1_idx;
    logic [15:0] n1_idx;

    assign slice_n1 = (mxu_cfg.slice_n + `N0 - 1) / `N0;
    assign slice_m1 = (mxu_cfg.slice_m + `M0 - 1) / `M0;
    always_ff @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            m1_idx <= 16'd0;
            n1_idx <= 16'd0;
        end else if (mxu_pmb_rd_req.vld && mxu_pmb_rd_req.rdy) begin
            if (last_req_in_instr) begin
                m1_idx <= 16'd0;
                n1_idx <= 16'd0;
            end else if (n1_idx == (slice_n1 - 16'd1)) begin
                n1_idx <= 16'd0;
                m1_idx <= m1_idx + 16'd1;
            end else begin
                n1_idx <= n1_idx + 16'd1;
            end
        end
    end

    logic [23:0] pmb_addr;
    assign pmb_addr                = pmb_base_addr + n1_idx * `N0 * `ACC_Byte;
    assign mxu_pmb_rd_req.pmb_addr = pmb_addr;
    assign mxu_pmb_rd_req.vld      = cfg_vld;
    assign last_req_in_instr       = (m1_idx == (slice_m1 - 16'd1)) && (n1_idx == (slice_n1 - 16'd1));

endmodule
